/**
 * @author Chris Wilcox
 * @author Preston Parrett
 * 
 * @date 2008/03/17
 * 
 * The Evolution program was written for UCSB's CS165b class.
 * 
 */

package evolution;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Panel;
import java.io.BufferedWriter;
import java.io.File;
import java.util.Hashtable;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Vector;
import java.io.*;
import java.util.*;


@SuppressWarnings("serial")
public class Stats extends Panel{

	public Stats() {
		Timer t = new Timer(true);
		t.schedule(new MyTask(this),1000,1000);
	}
	
	private class MyTask extends TimerTask {
		public MyTask(Stats s) {
			this.s = s; }
		Stats s;
		public void run() {
			s.paintIfNeeded(); }
	}
	
	private static Hashtable<String, Float> stats = new Hashtable<String,Float>();
	private static Hashtable<String, Integer> priority = new Hashtable<String,Integer>();
	private static Vector<String> list = new Vector<String>();
	
	private static final String logfileLoc = "life.log";
	private static final File logfile = new File(logfileLoc);
	
	
	public static final int RESET = 0xDEADBEEF;
	
	private static boolean needToUpdate = true;
	private static int maxPriority = 0;
	
	
	
	
	/**
	 * The name/value pair to be reported to the statistics class.
	 * 
	 * The string is the name of the statistic whose value we are
	 * changing. The value is the number by which we will increase
	 * (or decrease with negative values) the statistic.
	 * 
	 * A stat cannot be negative. (No decrementing zero)
	 * 
	 * All stats start at zero.
	 * 
	 * @param name the name of the statistic to add to.
	 * @param val a positive or negative integer. Pass RESET to reset to 0
	 */
	synchronized public static void report(String name, float val) {
		needToUpdate = true;
		Float oldVal = stats.get(name);
		if (oldVal == null) {
			if (val < 0) { val = new Integer(0); }
			stats.put(name,Float.valueOf(val));
			list.add(name);
		}
		else {
			Float newVal;
			if (val == RESET) {
				newVal = (float)0;
			} 
			else {
				newVal = oldVal+val;
				if (newVal < 0) { newVal = new Float(0); }
			}
			stats.put(name, Float.valueOf(newVal));
		}
	}
	
	synchronized public static void reportWithReset(String name, float val) {
		report(name,RESET);
		report(name,val);
	}
	
	synchronized public static void report(String name, float val, int priority) {
		Stats.priority.put(name, priority);
		if (priority > maxPriority) {
			maxPriority = priority;
		}
		report(name,val);
	}
	synchronized public static void reportWithReset(String name, float val,int priority) {
		report(name,RESET);
		report(name,val,priority);
	}
	
	synchronized public static double getStatValue(String name){
		Float val = stats.get(name);
		if(val == null){
			return 0;
		}
		return (double)Float.valueOf(val);
	}
	
	synchronized public static int getPriority(String name) {
		if (Stats.priority.get(name) == null) {
			return 0;
		}
		else {
			return Stats.priority.get(name);
		}
	}
	
	synchronized public static void resetAll() {
		stats = new Hashtable<String,Float>();
		list = new Vector<String>();
	}
	

		
	synchronized public static void log(String report) {
		try{
		BufferedWriter writer = new BufferedWriter(new FileWriter(logfile, true));	
		writer.write(report);
		writer.close();
		}
		catch (IOException e){
			System.err.println(e);
			System.exit(1);
		}
		
	}
	
	////////////////////////
	// GUI
	////////////////////////
	
	synchronized public void paint(Graphics g) {
		Hashtable<String,Float> h = stats;
		Hashtable<String,Integer> pri = priority;
		
		super.paint(g);
		g.setColor(Color.BLACK);
		g.drawRect(0, 0,getWidth()-1,getHeight()-1);
		
		int strLft=10,strUp=15; //Positioning
		
		int cnt = 0;
		g.setFont(new Font(null,Font.BOLD,14));
		g.drawString("World Statistics:", strLft,strUp);
		g.setFont(new Font(null,Font.PLAIN,12));
		
		int p=0;
		while (p<=maxPriority) {
			
			for ( String key : list ) {
				if (Stats.getPriority(key) == p) {
					g.drawString(key + ": " + stats.get(key), strLft, strUp*(1+cnt)+strUp);
					cnt++;
				}
			}
			p++;
		}
		
	}

	public void paintIfNeeded() {
		if (needToUpdate) {
			repaint();
		
		}
	}
}
